/*
 * server_app.h
 */

#include <exception>
#include <iostream>
#include <list>
#include <string>
#include "engine.h"
#include "server_app.h"
#include "session_dispatcher.h"
#include "../../common/src/debug.h"
#include "../../common/src/lock.h"
#include "../../common/src/message_queue.h"
#include "../../common/src/protocol.h"
#include "../../common/src/session.h"
#include "../../common/src/socket.h"
#include "../../common/src/synchro_list.h"
#include "../../common/src/synchro_vector.h"
#include "../../model/src/campaign.h"
#include "../../model/src/game.h"

ServerApp::ServerApp(int& port)
                    :q(),
                     sessions(),
                     campaigns(),
                     dispatcher(new SessionDispatcher(this, new Socket(port))),
                     engine(this),
                     t_dispatch(*dispatcher),
                     t_engine(engine) {
    running = true;
    loadData();
    t_dispatch.start();
    t_engine.start();
}

ServerApp::~ServerApp() {
    delete dispatcher;
    t_dispatch.join();
    t_engine.join();
    Lock lock(sessions.getMutex());
    std::list<Session*>* l = sessions.getList();
    for (std::list<Session*>::iterator it = l->begin(); it != l->end(); it++) {
        delete *it;
    }
    Lock campaigns_lock(campaigns.getMutex());
    std::vector<Campaign*>* v = campaigns.getVector();
    for (int i = 0; i < v->size(); ++i) {
        delete (*v)[i];
    }    
    while (!q.empty()) delete q.pop();
}

void ServerApp::exec() {
    std::string line;
    while (running) {
        getline(std::cin, line);
        if (line.length() == 0) continue;
        if (line.at(0) == CMD_EXIT) {
            running = false;
            continue;
        }
        //TODO: quitar
        broadcast(line);
    }
}

void ServerApp::broadcast(const std::string str_msg) {
    Message* msg;
    Lock lock(sessions.getMutex());
    std::list<Session*>* l = sessions.getList();
    for (std::list<Session*>::iterator it = l->begin(); it != l->end(); it++) {
        msg = new Message((*it)->getID(), Protocol::MSG_TEXT);
        msg->addRecord(str_msg);
        if ((*it)->isAlive()) (*it)->sendMessage(msg);
    }
}

//load campaigns, levels, resources, etc -->>> importante
void ServerApp::loadData() {
    std::string campaign_name("MyFirstCampaign");
    Level* levels[0];
    Campaign* campaign = new Campaign(1, campaign_name, NULL, 4, 2, levels, 0);
    Lock campaigns_lock(campaigns.getMutex());
    campaigns.getVector()->push_back(campaign);

    campaign_name = "MySecondCampaign";
    campaign = new Campaign(2, campaign_name, NULL, 4, 2, levels, 0);
    campaigns.getVector()->push_back(campaign);
}

bool& ServerApp::getRunning() {
    return running;
}

SynchroList<Session*>& ServerApp::getSessions() {
    return sessions;
}

SynchroVector<Campaign*>& ServerApp::getCampaigns() {
    return campaigns;
}

MessageQueue& ServerApp::getMessageQueue() {
    return q;
}

//{+}
